import shutil
import win32com
import win32com.client as win32
import logging
from pathlib import Path


class Run:
    def __init__(self, logger=None):
        """
        初始化 Run 类的实例。

        Args:
            logger (logging.Logger, optional): 可选的日志记录器对象。如果提供，则使用该日志记录器；否则创建一个新的日志记录器。默认值为 None。
        """
        formatter = logging.Formatter("%(asctime)s - %(levelname)s: %(message)s")  # 设置日志格式
        if logger:
            self.logger = logger
        else:
            # 设置日志
            self.logger = logging.getLogger("run")  # 创建日志
            self.logger.setLevel(logging.DEBUG)  # 设置日志等级
            # 添加控制台处理器
            console_handler = logging.StreamHandler()
            console_handler.setLevel(logging.DEBUG)
            console_handler.setFormatter(formatter)
            self.logger.addHandler(console_handler)

    def deep_search_folder(self, folder_path, func):
        """
        深度搜索文件夹。

        Args:
            folder_path (str): 要搜索的文件夹路径。
            func (callable): 对文件夹内每个文件执行的函数，该函数接受文件路径作为参数。

        Raises:
            RuntimeError: 当指定的文件夹不存在时抛出此异常。
        """
        folder_path = Path(folder_path)
        if not folder_path.exists():
            raise RuntimeError(f"文件夹{folder_path}不存在")
        for filename in folder_path.iterdir():
            sub_path = folder_path / filename
            if sub_path.is_dir():
                self.deep_search_folder(str(sub_path), func)
            func(str(sub_path))

    def copy_folder(self, source_folder_path, target_folder_path):
        """
        复制模板文件夹到目标文件夹。

        Args:
            source_folder_path (str): 源文件夹的路径。
            target_folder_path (str): 目标文件夹的路径。
        """
        shutil.copytree(source_folder_path, target_folder_path)  # 使用 shutil.copytree 复制整个文件夹
        self.logger.info(f"文件夹 {source_folder_path}")
        self.logger.info(f"已成功复制到 {target_folder_path}")

    def replace_word_content(self, file_path, old_words, new_words):
        """
        替换 word 文件内容。

        Args:
            file_path (str): 要处理的 word 文件的路径。
            old_words (str or list): 要替换的旧文本，可以是单个字符串或字符串列表。
            new_words (str or list): 替换后的新文本，可以是单个字符串或字符串列表。
        """
        if not isinstance(old_words, list):
            old_words = [old_words]
        if not isinstance(new_words, list):
            new_words = [new_words]
        try:
            wps_word = win32.gencache.EnsureDispatch("KWPS.Application")  # 创建 WPS 文字应用程序对象
        except AttributeError:
            shutil.rmtree(win32com.__gen_path__)
            wps_word = win32.gencache.EnsureDispatch("KWPS.Application")  # 创建 WPS 文字应用程序对象
        wps_word.Visible = False  # 让 WPS 窗口不可见
        doc = wps_word.Documents.Open(file_path)  # 打开指定的 WPS 文字文件
        for old_word, new_word in zip(old_words, new_words):
            doc.Content.Find.Execute(FindText=old_word, ReplaceWith=new_word, Replace=2)  # 替换文本
        doc.Save()  # 保存文档
        doc.Close()  # 关闭文档
        wps_word.Quit()  # 退出 WPS 文字应用程序

    def replace_excel_content(self, file_path, old_words, new_words):
        """
        替换 excel 文件内容。

        Args:
            file_path (str): 要处理的 excel 文件的路径。
            old_words (str or list): 要替换的旧文本，可以是单个字符串或字符串列表。
            new_words (str or list): 替换后的新文本，可以是单个字符串或字符串列表。
        """
        if not isinstance(old_words, list):
            old_words = [old_words]
        if not isinstance(new_words, list):
            new_words = [new_words]
        try:
            wps = win32.gencache.EnsureDispatch("KET.Application")  # 创建 WPS 表格应用程序对象
        except AttributeError:
            shutil.rmtree(win32com.__gen_path__)
            wps = win32.gencache.EnsureDispatch("KET.Application")  # 创建 WPS 表格应用程序对象
        wps.Visible = False  # 使 WPS 表格窗口不可见（可选）
        workbook = wps.Workbooks.Open(file_path)  # 打开指定的 WPS 表格文件
        for sheet in workbook.Sheets:
            cells = sheet.UsedRange
            for old_word, new_word in zip(old_words, new_words):
                cells.Replace(
                    What=old_word,
                    Replacement=new_word,
                    LookAt=win32.constants.xlPart,
                    SearchOrder=win32.constants.xlByRows,
                    MatchCase=False,
                    SearchFormat=False,
                    ReplaceFormat=False,
                )
        # 保存并关闭工作簿
        workbook.Save()
        workbook.Close()
        wps.Quit()
